--
-- DE2 (Cyclone-II) Entity for Interactive Project Game
-- Authors:
--      Abdulhamid Ghandour
--      Thomas John
--      Jaime Peretzman
--      Bharadwaj Vellore
--
-- Desc:
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity visionsystem is

port(
	clk : in std_logic;
	
	pixel_data : in unsigned (9 downto 0);
	valid_green : in std_logic;
	
	endofrow : in std_logic;
	endofframe : in std_logic;
	
	threshold : in unsigned (9 downto 0);
	
	xout : out unsigned (15 downto 0);
	yout : out unsigned (15 downto 0);
	
	no_detect : out std_logic
	);
	
end visionsystem;


architecture rtl of visionsystem is

signal CUEWIDTH : unsigned (15 downto 0) := x"0003";
	
signal xcount : unsigned (15 downto 0);
signal ycount : unsigned (15 downto 0);
signal darkpixelcount : unsigned (15 downto 0);
	
signal xmin : unsigned (15 downto 0);
signal xmax : unsigned (15 downto 0);
signal y_xmin : unsigned (15 downto 0);
signal y_xmax : unsigned (15 downto 0);
	
signal xstart : unsigned (15 downto 0);
	
signal cueinrow : std_logic;
signal cueinprevrow : std_logic;
	
signal verticalcue : std_logic;
	
signal xtemp : unsigned (15 downto 0);
signal ytemp : unsigned (15 downto 0);

signal cuetip : std_logic;

begin
	
xcounter : process(clk)
begin
	if rising_edge(clk) then
		if endofrow = '1' or endofframe = '1' then
			xcount <= (others => '0');
		elsif valid_green = '1' then
			xcount <= xcount + 1;
		end if;
	end if;
end process xcounter;

ycounter : process(clk)
begin
	if rising_edge(clk) then
		if endofframe = '1' then
			ycount <= (others => '0');
		elsif endofrow = '1' then
			ycount <= ycount + 1;
		end if;
	end if;
end process ycounter;

xminmax : process (clk)
variable darkpixelcount_comb : unsigned (15 downto 0);
variable xstart_comb : unsigned (15 downto 0);
begin
	if rising_edge(clk) then
		
		-----Dark Pixel Counter------
		if pixel_data < threshold and valid_green = '1' then
			darkpixelcount_comb := darkpixelcount + 1;
		else
			darkpixelcount_comb := x"0000";
		end if;
		
		if endofrow = '1' or endofframe = '1' then
			darkpixelcount <= (others => '0');
		elsif valid_green = '1' then
			darkpixelcount <= darkpixelcount_comb;
		end if;
		-----------------------------
		
		xstart_comb := xcount - CUEWIDTH + 1;
		
		if endofframe = '1' then
			xstart <= (others => '0');
			xmin <= x"FFFF";
			xmax <= (others => '0');
			y_xmin <= (others => '0');
			y_xmax <= (others => '0');			
			cueinprevrow <= '0';
			cueinrow <= '0';
		
		elsif endofrow = '1' then
			cueinprevrow <= cueinrow;
			cueinrow <= '0';
			
		else
			if darkpixelcount_comb = CUEWIDTH then
			
				cueinrow <= '1';
				xstart <= xstart_comb;
			
				if xstart_comb < xmin then
					xmin <= xstart_comb;
					y_xmin <= ycount;
				end if;
			end if;
		
			if darkpixelcount_comb >= CUEWIDTH then
		
				if xcount > xmax + 5 then
					xmax <= xcount;
					y_xmax <= ycount;
				end if;
			
			end if;
		
		end if;
		
	end if;

end process xminmax;

cuetip <= cueinrow xor cueinprevrow;

vertical_cue_detect : process(clk)
begin
	if rising_edge(clk) then
		if endofframe = '1' then
			xtemp <= x"0000";
			ytemp <= x"0000";
		elsif endofrow = '1' then
			if cuetip = '1' then
				xtemp <= xstart;
				ytemp <= ycount;
			end if;
		end if;
	end if;
end process vertical_cue_detect;

-- Set verticalcue if cue detected in first or last row
output : process(clk)
variable verticalcue_comb : std_logic;
begin
	if rising_edge(clk) then
		if ycount = x"0000" and endofrow = '1' then
			verticalcue <= cueinrow;
		elsif endofframe = '1' then
			verticalcue_comb := cueinprevrow or verticalcue;
			
			------Choose output----------
			if verticalcue_comb = '1' then
				xout <= xtemp;
				yout <= ytemp;
				no_detect <= '0';
			else
				if xmin = x"0000" then
					xout <= xmax;
					yout <= y_xmax;
					no_detect <= '0';
				else
					xout <= xmin;
					yout <= y_xmin;
					
					if xmin = x"FFFF" then
						no_detect <= '1';
					else
						no_detect <= '0';
					end if;
					
				end if;
			end if;
			-----------------------------
		
		end if;
	end if;
end process output;

end rtl;